iT邦幫忙

2023 iThome 鐵人賽

DAY 11
0

Hi,大家好,昨天我們完成了Sequelize 的套件安裝、資料庫連線的設定與資料表的設定,今天我們來預定要完成資料處理的模組,會依照查詢、新增、修改、刪除進行說明,相信今天內容,看過之後應該會明白為什麼當我使用了 Sequelize 之後,就很少寫 SQL 了XDDD,那麼就讓我們開始吧。

資料查詢

基本查詢

和某藥品一樣,Sequelize分成2種,分別是回傳單筆資料的findOne和回傳多筆資料的findAll,2者的用法都相同,最大的差異是回傳值的不同,findOne回傳的是封裝好的物件,findAll回傳的是物件陣列,其參數如下

cases.findOne({                       //資料表名稱為 cases
    attributes: ['caseid', 'casedesc', 'fromper', 'logdate'], //回傳欄位陣列
    where: {                         // 查詢條件
        caseid: "1"
    },
}).then((data) => {
    //查詢完成處理,通常我是先判斷取出之 data是不是 null,若不是 null ,將 dataValues後取出後回傳
    let result = {}
    if(data) {
        result = data.dataValues
    }
}).catch((err) => {
    //錯誤處理
})
//會被轉換成為 "SELECT caseid, casedesc, fromper, logdate from cases where caseid = '1' limit 1
cases.findAll({                       //資料表名稱為 cases
    attributes: ['caseid', 'casedesc', 'fromper', 'logdate'], //回傳欄位陣列
    where: {                         // 查詢條件
        caseid: "1"
    },
}).then((data) => {
    //查詢完成處理,通常我是會建立一個回傳用的陣列,只取出每個元素的 dataValues後回傳
    let result = []
    for(let i = 0; i < data.length; i++) {
        result.push(data[i].dataValues)
    }
}).catch((err) => {
    //錯誤處理
})
//會被轉換成為 "SELECT caseid, casedesc, fromper, logdate from cases where caseid = '1'

說明:

  1. attributes 為回傳欄位的陣列,若沒有指定的話,會回傳設定檔中所設定的所有欄位
  2. where 的規則和一般SQL中SELECT的WHERE語法相同
  3. 若查無資料的話,findAll 會產生空陣列,findOne 會產生 null,處理時需注意差異

多重條件

const Sequelize = require("sequelize")
const op = Sequelize.Op

cases.findAll({
    where: {
        caseid: "1",
        casedesc: {
            [op.like]: "%輸入問題%"
        }
    },
}).then((data) => {
    //…
})
//會被轉換成為 "SELECT caseid, casedesc, fromper, logdate from cases where caseid = '1' and casedesc like '%輸入問題%'

說明:

  1. 若where要下多重條件時,新增 where 物件的屬性即可
  2. 直接指定值的情形下,其產出的 where 條件均為「等於」,若要使用其他的運算子,列如>=、<、like、between…,需要引用 Sequelize.Op 套件,查詢條件改為 casedesc: {[op.like]: "%輸入問題%"},本範例為 like,若要查詢其他的運算子,請參照 官方文件

group by與 order

const Sequelize = require("sequelize")
const op = Sequelize.Op

cases.findAll({
    attributes: ['caseid'],
    where: {
        caseid: "1"
    },
    group: ['caseid'],
    order: [
        ['caseid', 'asc']
    ]
}).then((data) => {
    //…
})
//會被轉換成為 "SELECT caseid from cases where caseid = '1' group by caseid order by caseid

說明:

  1. group 之型態為欄位名稱的字串陣列,如同 SQL 的 GROUP BY 語法,需注意回傳的欄位數
  2. order 型態為二維陣列,其內容為 [ [排序檢欄位名稱, "asc"|"desc]],asc為由小到大排序,desc 為由大到小排序

資料新增

資料新增之功能,為呼叫 create function,把新增之物件傳入即可,範例如下

let obj = {}
//物件賦值
cases.create(obj)
.then((newobj)=>{
   //新增成功
}).catch((err) => {
    //錯誤處理
})

說明:

  1. 新增時回傳的內容為資料庫新增之整筆資料,可由這個機制,取回由資料庫產出之欄位內容,並回傳給前端,例如自動編號、UUID、欄位預設值…等
  2. Sequelize由於均依靠表格設定檔來產出 SQL 語法,因此若傳入之物件的屬性有與設定檔不同之處,會被套件忽略掉,多傳屬性不會造成系統錯誤

資料修改

資料更新之功能,為呼叫 update function,範例如下

let upobj = {}     //修改的資料
//物件賦值
let whereobj       // 條改條件物件
cases.update(updobj, {
where: whereobj
}).then((cnt)=>{
   //更新成功
}).catch((err) => {
    //錯誤處理
})

說明:

  1. where條件的使用方式,與findOne/findAll 相同
  2. 回傳值為資料庫中被更新的資料筆數,若條件不符,則回傳 0筆,可藉由回傳值 = 0與否判斷是否修改成功
  3. Sequelize由於均依靠表格設定檔來產出 SQL 語法,因此若傳入之物件的屬性有與設定檔不同之處,會被套件忽略掉,因此上述範例中的「updobj」多傳屬性不會造成系統錯誤,但是whereobj若有與資料表中不同之欄位,會出現錯誤,使用時請注意where條件之內容

資料刪除

資料刪除之功能,為呼叫 update function,範例如下

let upobj = {}     //修改的資料
//物件賦值
let whereobj       // 條改條件物件
cases.destory({
where: whereobj
}).then((cnt)=>{
   //更新成功
}).catch((err) => {
    //錯誤處理
})

說明:

  1. where條件的使用方式,與findOne/findAll 相同
  2. 回傳值為資料庫中被刪除的資料筆數,若條件不符,則回傳 0筆,可藉由回傳值 = 0與否判斷是否修改成功

完成資料處理模組

綜合上述之說明,本日先完成顯示客服資料列表的查詢功能,並預留查詢條件的處理功能,供後續之用

'use strict';
const cases = require("./db/cases")
const Sequelize = require("sequelize");
const op = Sequelize.Op

module.exports = {

    /**
     * 取出客服資料列表
     * @param {*} qry 篩選條件
     */
    getCases: async(qry)=> {
        return new Promise((resolve, reject) => {
            let qryobj = {}
            if(qry) {
                // 處理查詢條件
                if(qry.caseid) {
                    qryobj.caseid = qry.caseid
                }
                if(qry.casedesc) {
                    qryobj.casedesc = {[op.like]: "%" + qry.casedesc + "%"}
                }
                if(qry.fromper) {
                    qryobj.fromper = {[op.like]: qry.fromper + "%"}
                }
            }
            cases.findAll({
                attributes: ['caseid', 'casedesc', 'fromper', 'logdate'],
                where: qryobj
            })
            .then((data) => {
                let result = []
                for(let i = 0; i < data.length; i++) {
                    result.push(data[i].dataValues)
                    //資料超過 50 筆僅取出前 50筆
                    if(i >= 50) {
                        break;
                    }
                }
                resolve(result)
            }).catch((err) => {
                reject(err.message)
            })
        })
    }
}

//說明:
如上述程式碼,Sequelize 最方便的地方在於多重條件的處理方式,我們只要調整 qryobj 的內容,就可以做出交叉查詢的功能,相較傳統組合 SQL 語法的做法,Sequelize 是簡單很多的

結語

今天了解了 Sequelize 的資料增、刪、查、改的方式,相較傳統組合 SQL 語法的做法,Sequelize 是簡單很多的,例如交叉查詢功能,不用像使用 SQL 方式去串接 WHERE子句的文字。資料新增、修改時,也不用去核對欄位名稱,串接長長的SQL語法。只要把物件做出來(通常是從前端直接取得後,整個物件傳到 model 中),再加上特定由後端運算產生之資料,傳入 create / update fuction中,即完成資料庫的新增修改,用久了很容易回不去 XDDD。
明天預計正式進入 vue.js 的部份,那我們明天再繼續吧


上一篇
資料庫處理#1
下一篇
vue.js 初體驗
系列文
以vue.js + node.js 搭建一個客服填單系統30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言